local skynet = require 'skynet'
local mdb = require 'mc.mdb'
local log = require 'mc.logging'
local ctx = require 'mc.context'
local local_path = '/bmc/kepler/Managers/1/ActiveStandby/Local'
local remote_path = '/bmc/kepler/Managers/1/ActiveStandby/Remotes/ActiveStandbyRemote_0_01'
local status_intf = 'bmc.kepler.Managers.ActiveStandby.Status'
local local_intf = 'bmc.kepler.Managers.ActiveStandby.Local'
local remote_intf = 'bmc.kepler.Managers.ActiveStandby.Remote'
local accessor_path = '/bmc/kepler/Accessor/Accessor_ActiveRead_01'
local accessor_intf = 'bmc.kepler.Accessor'
local switch_rule_active_path = '/bmc/kepler/Managers/1/ActiveStandby/SwitchRules/SwitchRule_active_00'
local switch_rule_standby_path = '/bmc/kepler/Managers/1/ActiveStandby/SwitchRules/SwitchRule_standby_00'
local switch_rule_not_allow_path = '/bmc/kepler/Managers/1/ActiveStandby/SwitchRules/SwitchRule_not_allow_00'
local switch_rule_intf = 'bmc.kepler.Managers.ActiveStandby.SwitchRule'

require 'active_standby_mgmt.json_types.Local'
require 'active_standby_mgmt.json_types.Remote'
require 'active_standby_mgmt.json_types.Status'
require 'active_standby_mgmt.json_types.SwitchRule'
require 'active_standby_mgmt.json_types.Accessor'

local service = 'bmc.kepler.active_standby_mgmt'

local local_object, remote_object, accessor_object, switch_rule_active_object, switch_rule_standby_object,
    switch_rule_not_allow_object, rpc_object, bus

local interface_cases = {}
interface_cases.__index = interface_cases

function interface_cases.check_object_status()
    log:notice('------- check object status start -------')
    -- 初始为备
    assert(local_object.ActiveStatus == 0, 'actual: ' .. local_object.ActiveStatus)
    assert(remote_object.ActiveStatus == 0, 'actual: ' .. remote_object.ActiveStatus)
    log:notice('------- check object status end -------')
end

function interface_cases.test_switch_status()
    log:notice('------- test switch status start -------')
    -- 切换条件命中升主
    switch_rule_active_object.Reading = 1
    switch_rule_active_object.Reading = 0
    skynet.sleep(100)  -- 等待1s（100）轮询检测
    -- 触发禁止条件
    switch_rule_not_allow_object.Reading = 2  -- 读值2触发条件禁止升主
    -- 调用接口会失败
    local ok = pcall(function()
        rpc_object:SwitchStatus(ctx.new(), 1)
    end)
    assert(not ok)
    -- 恢复条件后重试预期成功，因为符合倒换条件
    switch_rule_not_allow_object.Reading = 1
    ok = pcall(function()
        rpc_object:SwitchStatus(ctx.new(), 1)
    end)
    assert(not ok)
    -- 需要手动改信号触发升主
    accessor_object.Value = 1
    skynet.sleep(50)  -- 等待0.5s（50）检测信号
    assert(local_object.ActiveStatus == 0, 'actual: ' .. local_object.ActiveStatus)
    assert(remote_object.ActiveStatus == 0, 'actual: ' .. remote_object.ActiveStatus)
    -- 重复升主预期失败
    ok = pcall(function()
        rpc_object:SwitchStatus(ctx.new(), 1)
    end)
    assert(not ok)
    -- 降备也会失败，因为倒换抑制中
    ok = pcall(function()
        rpc_object:SwitchStatus(ctx.new(), 0)
    end)
    assert(not ok)
    -- 主动降备实际不会生效，主要观察是否有错误日志
    switch_rule_standby_object.Reading = 1
    switch_rule_standby_object.Reading = 0
    -- 手动降备
    accessor_object.Value = 0
    skynet.sleep(50)  -- 等待0.5s（50）检测信号
    assert(local_object.ActiveStatus == 0, 'actual: ' .. local_object.ActiveStatus)
    -- DT中无法自动更新远端节点的硬件主备状态，当前暂时不校验
    -- assert(remote_object.ActiveStatus == 1, 'actual: ' .. remote_object.ActiveStatus)
    log:notice('------- test switch status end -------')
end

function interface_cases.test_on_dump(bus)
    log:notice('------- test dump start -------')
    -- 回调函数不支持代理对象访问，这地方直接使用busctl访问方式进行测试
    local debug_path = '/bmc/kepler/active_standby_mgmt/MicroComponent'
    local debug_intf = 'bmc.kepler.MicroComponent.Debug'
    local dump_path = skynet.getenv('DUMP_FILE_PATH')
    -- 无效路径测试
    bus:call(service, debug_path, debug_intf, 'Dump', 'a{ss}s', ctx.new(), dump_path .. 'test')
    local info_file = io.open(dump_path .. '/asm_info.txt', 'r')
    assert(not info_file)
    -- 有效路径
    bus:call(service, debug_path, debug_intf, 'Dump', 'a{ss}s', ctx.new(), dump_path)
    info_file = io.open(dump_path .. '/asm_info.txt', 'r')
    assert(info_file)
    info_file:close()
    log:notice('------- test dump end -------')
end

function interface_cases.init_object(local_bus)
    log:notice('------- init object start -------')
    bus = local_bus
    local_object = mdb.get_object(bus, local_path, status_intf)
    rpc_object = mdb.get_object(bus, local_path, local_intf)
    remote_object = mdb.get_object(bus, remote_path, status_intf)
    accessor_object = mdb.get_object(bus, accessor_path, accessor_intf)
    switch_rule_active_object = mdb.get_object(bus, switch_rule_active_path, switch_rule_intf)
    switch_rule_standby_object = mdb.get_object(bus, switch_rule_standby_path, switch_rule_intf)
    switch_rule_not_allow_object = mdb.get_object(bus, switch_rule_not_allow_path, switch_rule_intf)
    -- 默认寄存器信号时非法值，这里改为Standby
    accessor_object.Value = 0
    log:notice('------- init object end -------')
end

function interface_cases.test_entry(local_bus)
    log:notice('------- test entry start -------')
    interface_cases.init_object(local_bus)
    -- 查看初始信息是否符合预期
    interface_cases.check_object_status()
    -- 测试状态倒换
    interface_cases.test_switch_status()
    -- dump日志
    interface_cases.test_on_dump(bus)
    log:notice('------- test entry end -------')
end

return interface_cases

